home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue37 / Alfresco / VSortFns.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1998-07-27  |  11.8 KB  |  353 lines

  1. {*********************************************************}
  2. {* VSortFns                                              *}
  3. {* Copyright (c) Julian M Bucknall 1998                  *}
  4. {* All rights reserved.                                  *}
  5. {*********************************************************}
  6. {* Sort routines for visual display                      *}
  7. {*********************************************************}
  8.  
  9. {Note: this unit is released as freeware. In other words, you are free
  10.        to use this unit in your own applications, however I retain all
  11.        copyright to the code. JMB}
  12.  
  13. unit VSortFns;
  14.  
  15. interface
  16.  
  17. uses
  18.   StdCtrls,
  19.   SysUtils;
  20.  
  21. type
  22.   TSortElement = integer;
  23.  
  24.   TLessFunction = function (X, Y : TSortElement) : boolean;
  25.   TSwapFunction = procedure (var A    : array of integer;
  26.                                  I, J : integer);
  27.   TSetFunction = procedure (var A : array of integer;
  28.                                 X : TSortElement;
  29.                                 I : integer);
  30.  
  31. procedure VisualBubbleSort(var A           : array of integer;
  32.                                Left, Right : integer;
  33.                                LessFunc    : TLessFunction;
  34.                                SwapProc    : TSwapFunction);
  35.  
  36. procedure VisualShakerSort(var A           : array of integer;
  37.                                Left, Right : integer;
  38.                                LessFunc    : TLessFunction;
  39.                                SwapProc    : TSwapFunction);
  40.  
  41. procedure VisualSelectionSort(var A           : array of integer;
  42.                                   Left, Right : integer;
  43.                                   LessFunc    : TLessFunction;
  44.                                   SwapProc    : TSwapFunction);
  45.  
  46. procedure VisualInsertionSort(var A           : array of integer;
  47.                                   Left, Right : integer;
  48.                                   LessFunc    : TLessFunction;
  49.                                   SetProc     : TSetFunction);
  50.  
  51. procedure VisualBestInsertionSort(var A           : array of integer;
  52.                                       Left, Right : integer;
  53.                                       LessFunc    : TLessFunction;
  54.                                       SwapProc    : TSwapFunction;
  55.                                       SetProc     : TSetFunction);
  56.  
  57. procedure VisualShellsort(var A           : array of integer;
  58.                               Left, Right : integer;
  59.                               LessFunc    : TLessFunction;
  60.                               SwapProc    : TSwapFunction;
  61.                               SetProc     : TSetFunction);
  62.  
  63. procedure VisualQuicksort(var A           : array of integer;
  64.                               Left, Right : integer;
  65.                               LessFunc    : TLessFunction;
  66.                               SwapProc    : TSwapFunction);
  67.  
  68. procedure VisualBestQuicksort(var A           : array of integer;
  69.                                   Left, Right : integer;
  70.                                   LessFunc    : TLessFunction;
  71.                                   SwapProc    : TSwapFunction;
  72.                                   SetProc     : TSetFunction);
  73.  
  74. implementation
  75.  
  76. procedure VisualBubbleSort(var A           : array of integer;
  77.                                Left, Right : integer;
  78.                                LessFunc    : TLessFunction;
  79.                                SwapProc    : TSwapFunction);
  80. var
  81.   i, j : integer;
  82. begin
  83.   for i := Left to pred(Right) do
  84.     for j := Right downto succ(i) do
  85.       if LessFunc(A[j], A[j-1]) then
  86.         SwapProc(A, j-1, j);
  87. end;
  88.  
  89. procedure VisualShakerSort(var A           : array of integer;
  90.                                Left, Right : integer;
  91.                                LessFunc    : TLessFunction;
  92.                                SwapProc    : TSwapFunction);
  93. var
  94.   i : integer;
  95. begin
  96.   while (Left < Right) do begin
  97.     for i := Right downto succ(Left) do
  98.       if LessFunc(A[i], A[i-1]) then
  99.         SwapProc(A, i-1, i);
  100.     inc(Left);
  101.     for i := succ(Left) to Right do
  102.       if LessFunc(A[i], A[i-1]) then
  103.         SwapProc(A, i-1, i);
  104.     dec(Right);
  105.   end;
  106. end;
  107.  
  108.  
  109. procedure VisualSelectionSort(var A           : array of integer;
  110.                                   Left, Right : integer;
  111.                                   LessFunc    : TLessFunction;
  112.                                   SwapProc    : TSwapFunction);
  113. var
  114.   i, j : integer;
  115.   IndexOfMin : integer;
  116. begin
  117.   for i := Left to pred(Right) do begin
  118.     IndexOfMin := i;
  119.     for j := succ(i) to Right do
  120.       if LessFunc(A[j], A[IndexOfMin]) then
  121.         IndexOfMin := j;
  122.     SwapProc(A, i, IndexOfMin);
  123.   end;
  124. end;
  125.  
  126. procedure VisualInsertionSort(var A           : array of integer;
  127.                                   Left, Right : integer;
  128.                                   LessFunc    : TLessFunction;
  129.                                   SetProc     : TSetFunction);
  130. var
  131.   i, j : integer;
  132.   Temp : TSortElement;
  133. begin
  134.   for i := succ(Left) to Right do begin
  135.     Temp := A[i];
  136.     j := i;
  137.     while (j > Left) and LessFunc(Temp, A[j-1]) do begin
  138.       SetProc(A, A[j-1], j);
  139.       dec(j);
  140.     end;
  141.     SetProc(A, Temp, j);
  142.   end;
  143. end;
  144.  
  145. procedure VisualBestInsertionSort(var A           : array of integer;
  146.                                       Left, Right : integer;
  147.                                       LessFunc    : TLessFunction;
  148.                                       SwapProc    : TSwapFunction;
  149.                                       SetProc     : TSetFunction);
  150. var
  151.   i, j : integer;
  152.   IndexOfMin : integer;
  153.   Temp : TSortElement;
  154. begin
  155.   {find the smallest element and put it in the first position}
  156.   IndexOfMin := Left;
  157.   for i := succ(Left) to Right do
  158.     if LessFunc(A[i], A[IndexOfMin]) then
  159.       IndexOfMin := i;
  160.   if (Left <> IndexOfMin) then
  161.     SwapProc(A, Left, IndexOfMin);
  162.   {now sort via insertion method}
  163.   for i := Left+2 to Right do begin
  164.     Temp := A[i];
  165.     j := i;
  166.     while LessFunc(Temp, A[j-1]) do begin
  167.       SetProc(A, A[j-1], j);
  168.       dec(j);
  169.     end;
  170.     SetProc(A, Temp, j);
  171.   end;
  172. end;
  173.  
  174. procedure VisualShellsort(var A           : array of integer;
  175.                               Left, Right : integer;
  176.                               LessFunc    : TLessFunction;
  177.                               SwapProc    : TSwapFunction;
  178.                               SetProc     : TSetFunction);
  179. var
  180.   i, j : integer;
  181.   h    : integer;
  182.   Temp : TSortElement;
  183. begin
  184.   {firstly calculate the first h value we shall use: it'll be about
  185.    one ninth of the number of the elements}
  186.   h := 1;
  187.   while (h <= (Right - Left) div 9) do
  188.     h := (h * 3) + 1;
  189.   {start a loop that'll decrement h by one third each time through}
  190.   while (h > 0) do begin
  191.     {now insertion sort each h-subfile}
  192.     for i := (Left + h) to Right do begin
  193.       Temp := A[i];
  194.       j := i;
  195.       while (j >= (Left + h)) and LessFunc(Temp, A[j-h]) do begin
  196.         SetProc(A, A[j-h], j);
  197.         dec(j, h);
  198.       end;
  199.       SetProc(A, Temp, j);
  200.     end;
  201.     {decrease h by a third}
  202.     h := h div 3;
  203.   end;
  204. end;
  205.  
  206. procedure VisualQuicksort(var A           : array of integer;
  207.                               Left, Right : integer;
  208.                               LessFunc    : TLessFunction;
  209.                               SwapProc    : TSwapFunction);
  210.   function Partition(L, R : integer) : integer;
  211.   var
  212.     i, j : integer;
  213.     Temp : TSortElement;
  214.   begin
  215.     {set up the indexes}
  216.     i := L;
  217.     j := pred(R);
  218.     {get the partition element}
  219.     Temp := A[R];
  220.     {do forever (we'll break out of the loop when needed)}
  221.     while true do begin
  222.       {find the first element greater than or equal to the partition
  223.        element from the left; note that our partition element will
  224.        stop this loop}
  225.       while LessFunc(A[i], Temp) do
  226.         inc(i);
  227.       {find the first element less than the partition element from the
  228.        right; check to break out of the loop if we hit the left
  229.        element - we have no sentinel there}
  230.       while LessFunc(Temp, A[j]) do begin
  231.         if (j = L) then
  232.           Break;
  233.         dec(j);
  234.       end;
  235.       {if we crossed get out of this infinite loop to swap the
  236.        partition element into place}
  237.       if (i >= j) then
  238.         Break;
  239.       {otherwise swap the two out-of-place elements}
  240.       SwapProc(A, i, j);
  241.       {and continue}
  242.       inc(i);
  243.       dec(j);
  244.     end;
  245.     {swap the partition element into place, return the dividing index}
  246.     SwapProc(A, i, R);
  247.     Result := i;
  248.   end;
  249.   procedure QuickSortPrim(L, R : integer);
  250.   var
  251.     DividingItem : integer;
  252.   begin
  253.     {stop the recursion, if needed}
  254.     if (R - L) <= 0 then
  255.       Exit;
  256.     {otherwise, partition about the final element in the set}
  257.     DividingItem := Partition(L, R);
  258.     {recursively quicksort the two subsets either side of the dividing
  259.      element}
  260.     QuickSortPrim(L, pred(DividingItem));
  261.     QuickSortPrim(succ(DividingItem), R);
  262.   end;
  263. begin
  264.   {start it all off}
  265.   QuickSortPrim(Left, Right);
  266. end;
  267.  
  268. procedure VisualBestQuicksort(var A           : array of integer;
  269.                                   Left, Right : integer;
  270.                                   LessFunc    : TLessFunction;
  271.                                   SwapProc    : TSwapFunction;
  272.                                   SetProc     : TSetFunction);
  273.   function Partition(L, R : integer) : integer;
  274.   var
  275.     i, j : integer;
  276.     Temp : TSortElement;
  277.   begin
  278.     {set up the indexes}
  279.     i := L;
  280.     j := pred(R);
  281.     {get the partition element}
  282.     Temp := A[R];
  283.     {do forever (we'll break out of the loop when needed)}
  284.     while true do begin
  285.       {find the first element greater than or equal to the partition
  286.        element from the left; note that our partition element will
  287.        stop this loop}
  288.       while LessFunc(A[i], Temp) do
  289.         inc(i);
  290.       {find the first element less than the partition element from the
  291.        right; note the median-of-three algorithm has ensured we have
  292.        a sentinel on the left}
  293.       while not LessFunc(A[j], Temp) do
  294.         dec(j);
  295.       {if we crossed get out of this infinite loop to swap the
  296.        partition element into place}
  297.       if (i >= j) then
  298.         Break;
  299.       {otherwise swap the two out-of-place elements}
  300.       SwapProc(A, i, j);
  301.       {and continue}
  302.       inc(i);
  303.       dec(j);
  304.     end;
  305.     {swap the partition element into place, return the dividing index}
  306.     SwapProc(A, i, R);
  307.     Result := i;
  308.   end;
  309.   procedure QuickSortPrim(L, R : integer);
  310.   var
  311.     DividingItem : integer;
  312.     Temp : TSortElement;
  313.     i, j : integer;
  314.   begin
  315.     {if needed, stop the recursion at the cut-off point, and insertion
  316.      sort}
  317.     if (R - L) <= 10 then begin
  318.       for i := succ(L) to R do begin
  319.         Temp := A[i];
  320.         j := i;
  321.         while (j > L) and LessFunc(Temp, A[j-1]) do begin
  322.           SetProc(A, A[j-1], j);
  323.           dec(j);
  324.         end;
  325.         SetProc(A, Temp, j);
  326.       end;
  327.       Exit;
  328.     end;
  329.     {calculate the median-of-three element; for an extra bit of speed,
  330.      put the smallest element of the three in the first position, the
  331.      greatest in the last position, and the median in the last-but-one
  332.      position and partition a smaller subset excluding the first and
  333.      last}
  334.     SwapProc(A, (L+R) shr 1, pred(R));
  335.     if not LessFunc(A[L], A[pred(R)]) then
  336.       SwapProc(A, L, pred(R));
  337.     if not LessFunc(A[L], A[R]) then
  338.       SwapProc(A, L, R);
  339.     if not LessFunc(A[pred(R)], A[R]) then
  340.       SwapProc(A, pred(R), R);
  341.     DividingItem := Partition(succ(L), pred(R));
  342.     {recursively quicksort the two subsets either side of the dividing
  343.      element}
  344.     QuickSortPrim(L, pred(DividingItem));
  345.     QuickSortPrim(succ(DividingItem), R);
  346.   end;
  347. begin
  348.   {start it all off}
  349.   QuickSortPrim(Left, Right);
  350. end;
  351.  
  352. end.
  353.